/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package crm.salesOrderProcessing.session;

import commonInfrastructure.accountManagement.entity.SalesmanEntity;
import crm.clientManagement.entity.CompanyEntity;
import crm.clientManagement.session.CompanySessionBean;
import frm.creditControl.session.CreditControlSessionBean;
import frm.creditControl.util.exception.FinanceException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import mrp.productionPlanning.session.MRPATPSessionBean;
import mrp.productionPlanning.util.exception.MRPException;
import crm.salesOrderProcessing.entity.LineItemEntity;
import crm.salesOrderProcessing.entity.SalesOrderEntity;
import crm.salesOrderProcessing.entity.SalesQuotationEntity;
import crm.salesOrderProcessing.util.exception.*;
import scm.supplyChainManagement.session.DeliveryOrderSessionBean;

/**
 *
 * @author ReinForceII
 */
@Stateless
@LocalBean
public class SalesOrderSessionBean {

    @PersistenceContext
    private EntityManager em;
    @EJB
    SalesQuotationSessionBean salesQuotationSessionBean;
    @EJB
    CreditControlSessionBean creditControlSessionBean;
    @EJB
    MRPATPSessionBean mRPATPSessionbean;
    @EJB
    CompanySessionBean companySessionBean;
    @EJB
    PriceManagementSessionBean priceManageSessionBean;
    @EJB
    DeliveryOrderSessionBean deliveryOrderSessionBean;

    public void confirmSalesOrder(SalesmanEntity salesman, SalesOrderEntity salesOrder) throws SalesmanAmountLimitExceededException, SalesmanNotExistException, SalesOrderStatusMismatchException {

        if (salesman == null) {
            throw new SalesmanNotExistException();
        }

        if (salesOrder.getStatusId() != 400) {
            throw new SalesOrderStatusMismatchException("Current Status Id is: " + salesOrder.getStatusId());
        }
        if (salesman.getAmountLimit() >= salesOrder.getTotalAmount()) {
            salesOrder.setConfirmedBy(salesman);
            salesOrder.setStatusId(500);
            salesOrder.setDateConfirmed(Calendar.getInstance().getTime());
            saveChanges(salesOrder);
            return;
        }
        throw new SalesmanAmountLimitExceededException();
    }

    public void confirmPendingOrder(SalesmanEntity salesman, SalesOrderEntity salesOrder, boolean skip) throws SalesmanAmountLimitExceededException, SalesmanNotExistException, SalesOrderStatusMismatchException {


        if (salesman == null) {
            throw new SalesmanNotExistException();
        }

        if (salesOrder.getStatusId() != 100) {
            throw new SalesOrderStatusMismatchException("Current status Id: " + salesOrder.getStatusId());
        }

        if (salesman.getAmountLimit() >= salesOrder.getTotalAmount()) {
            salesOrder.setLargeOrderConfirmedBy(salesman);
            salesOrder.setStatusId(200);
            saveChanges(salesOrder);

        } else {
            throw new SalesmanAmountLimitExceededException();
        }

        if (skip && (salesOrder.getStatusId() == 200)) {
            salesOrder.setConfirmedBy(salesman);
            salesOrder.setSkipConfirm(true); //This is for skipping final confirmation, thus I kept this line when converting to status Id
            salesOrder.setDateConfirmed(Calendar.getInstance().getTime());
        }


    }

    public void verifySalesOrder(SalesOrderEntity salesOrder) throws FinanceException, MRPException {

        if (!salesOrder.isCashInAdvance()) {
            creditControlSessionBean.creditCheck(salesOrder);
        }
        mRPATPSessionbean.aTPCheck(salesOrder);

        return;
    }

    public List<SelectItem> getProductList(SalesOrderEntity salesOrder) {

        if (salesOrder == null) {
            return new ArrayList<SelectItem>();
        } else {

            List<LineItemEntity> lineItems = salesOrder.getSalesOrderLineItems();

            List<SelectItem> selectItems = new ArrayList<SelectItem>();


            for (LineItemEntity lineItem : lineItems) {

                selectItems.add(new SelectItem(lineItem.getProduct().getId(), lineItem.getProduct().getProductName()));
            }
            return selectItems;
        }
    }

    //this method is not used by any, should we keep it still?
//    private boolean verifyAmountLimit(SalesmanEntity salesman, double totalAmount) {
//
//        if (salesman.getAmountLimit() >= totalAmount) {
//            return true;
//        } else {
//            return false;
//        }
//
//    }
//    public boolean generateDeliveryOrders(SalesOrderEntity salesOrder) {
//        List<DeliveryOrderEntity> deliveryOrderList = new ArrayList();
//        boolean deliveryOrderExists = false;
//                
//        for (LineItemEntity item : salesOrder.getSalesOrderLineItems()){
//            deliveryOrderExists = false;
//            
//            for (DeliveryOrderEntity deliveryOrder : deliveryOrderList){
//                
//                    if (deliveryOrder.getDeliveryDate().equals(item.getDeliveryDate()))
//                    {
//                        deliveryOrderExists = true;
//                        deliveryOrder.getLineItems().add(item);
//                        deliveryOrderSessionBean.saveChanges(deliveryOrder);
//                        break;
//                    }
//            }
//            
//            if (!deliveryOrderExists){
//                
//                DeliveryOrderEntity deliveryOrder = new DeliveryOrderEntity();
//                
//                deliveryOrder.setDeliveryDate(item.getDeliveryDate());
//                deliveryOrder.setGenerateDate(Calendar.getInstance().getTime());
//                
//                List<LineItem> lineItems = new ArrayList();
//                lineItems.add(item);
//                deliveryOrder.setLineItems(lineItems);
//                
//                deliveryOrder.setPaid(false);
//
//                deliveryOrder.setParentSalesOrder(salesOrder);
//                deliveryOrderList.add(deliveryOrder);
//                
//                deliveryOrderSessionBean.addDeliveryOrder(deliveryOrder);
//            }
//        }
//        
//
//
//        return true;
//    }
    public void addSalesOrder(SalesOrderEntity salesOrder) {
        em.persist(salesOrder);
    }

    public void saveChanges(SalesOrderEntity salesOrder) {
        em.merge(salesOrder);
    }

    public void saveChanges(SalesOrderEntity salesOrder, Collection<LineItemEntity> lineItems) {
        /* TODO: How to save changes?
        for (LineItemEntity item : lineItems) {
        em.merge(item);
        }*/
        em.merge(salesOrder);
    }

    public void deleteSalesOrder(Long id) {
        SalesOrderEntity salesOrder = em.find(SalesOrderEntity.class, id);
        em.remove(salesOrder);
    }

    public List<SalesOrderEntity> getAllSalesOrders(SalesmanEntity user)  { // Returns only confirmed salesorder

        Query query = em.createQuery("SELECT so FROM SalesOrderEntity so");
        List<SalesOrderEntity> result = new ArrayList();
        
        result = query.getResultList();
        for (SalesOrderEntity salesOrder : result){
            if (!salesOrder.getProcessedBy().equals(user))
                result.remove(salesOrder);
        }
        
        return result;
        
        
        
        
        
        
        
        //        if (user.getSalesManLevel().equals("4")) {
//            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.largeOrderConfirmed = 1 AND sl.verifiedBySystem = 1 ");
//
//            List<SalesOrderEntity> salesOrders = null;
//            try {
//                salesOrders = query.getResultList();
//            } catch (NoResultException ex) {
//                throw new NoPurchaseOrderException();
//            }
//            return salesOrders;
//        } else {
//            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.processedBy = :inUserId AND sl.largeOrderConfirmed = 1 AND sl.verifiedBySystem = 1");
//            query.setParameter("inUserId", user);
//            List<SalesOrderEntity> salesOrders = null;
//            try {
//                salesOrders = query.getResultList();
//            } catch (NoResultException ex) {
//                throw new NoPurchaseOrderException();
//            }
//            return salesOrders;
//        }
    }

    public List<SalesOrderEntity> getPendingLargeOrders(SalesmanEntity user) throws NoPurchaseOrderException { // Returns only confirmed salesorder
        if (user.getSalesManLevel().equals("4")) {
            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE  sl.verifiedBySystem = 0 AND sl.largeOrderConfirmed = 1 ");

            List<SalesOrderEntity> salesOrders = null;
            try {
                salesOrders = query.getResultList();
            } catch (NoResultException ex) {
                throw new NoPurchaseOrderException();
            }
            return salesOrders;
        } else {
            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.processedBy = :inUserId  AND sl.verifiedBySystem = 0 AND sl.largeOrderConfirmed = 1");
            query.setParameter("inUserId", user);
            List<SalesOrderEntity> salesOrders = null;
            try {
                salesOrders = query.getResultList();
            } catch (NoResultException ex) {
                throw new NoPurchaseOrderException();
            }
            return salesOrders;
        }
    }

    public List<SalesOrderEntity> getAllFinalSalesOrder(SalesmanEntity user) throws NoSalesOrderException { // Returns only not confimed salesorder (purchase order)
        if (user.getSalesManLevel().equals("4")) {
            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.confirmed = 1");

            List<SalesOrderEntity> salesOrders = null;
            try {
                salesOrders = query.getResultList();
            } catch (NoResultException ex) {
                throw new NoSalesOrderException();
            }
            return salesOrders;
        } else {
            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.confirmed = 1 AND sl.processedBy = :inUserId");
            query.setParameter("inUserId", user);
            List<SalesOrderEntity> salesOrders = null;

            try {
                salesOrders = query.getResultList();
            } catch (NoResultException e) {
                throw new NoSalesOrderException();
            }
            return salesOrders;
        }
    }

//    public List<SalesOrderEntity> getAllPendingOrders(SalesmanEntity user) throws NoPurchaseOrderException {
//        // Returns only not confimed salesorder (purchase order)
//        if (user.getSalesManLevel().equals("4")) {
//            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.largeOrderConfirmed = 0 AND sl.verifiedBySystem = 0");
//
//            List<SalesOrderEntity> salesOrders = null;
//            try {
//                salesOrders = query.getResultList();
//            } catch (NoResultException ex) {
//                throw new NoPurchaseOrderException();
//            }
//            return salesOrders;
//        } else {
//            Query query = em.createQuery("SELECT sl FROM SalesOrderEntity sl WHERE sl.largeOrderConfirmed = 0 AND sl.processedBy = :inUserId AND sl.verifiedBySystem = 0");
//            query.setParameter("inUserId", user);
//            List<SalesOrderEntity> salesOrders = null;
//
//            try {
//                salesOrders = query.getResultList();
//            } catch (NoResultException e) {
//                throw new NoPurchaseOrderException();
//            }
//            return salesOrders;
//        }
//    }
    //recently changed, retrieve the purchaseOrder
    public SalesOrderEntity getSalesOrderById(Long id) {
        return em.find(SalesOrderEntity.class, id);
    }
}
